package org.liu.simpleTank;

import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;

public class KeyMonitor {
	private ControlStatus userInput;
	private ArrayList<Integer> keys = new ArrayList<Integer>(4);
	{
		userInput = new ControlStatus();
	}
	public KeyMonitor() {
		keyAdapter = new KeyAdapter() {
			// pending dir key
			private final int upKey = KeyEvent.VK_W;
			private final int rightKey = KeyEvent.VK_D;
			private final int downKey = KeyEvent.VK_S;
			private final int leftKey = KeyEvent.VK_A;
			private final int fireKey = KeyEvent.VK_J;
			// bidirectional map
			private HashMap<Integer, Integer> keyToDir = new HashMap<Integer, Integer>(4);
			private HashMap<Integer, Integer> dirToKey = new HashMap<Integer, Integer>(4);
			{
				keyToDir.put(upKey, CONSTS.UP);
				keyToDir.put(rightKey, CONSTS.RIGHT);
				keyToDir.put(downKey, CONSTS.DOWN);
				keyToDir.put(leftKey, CONSTS.LEFT);
				
				dirToKey.put(CONSTS.UP, upKey);
				dirToKey.put(CONSTS.RIGHT, rightKey);
				dirToKey.put(CONSTS.DOWN, downKey);
				dirToKey.put(CONSTS.LEFT, leftKey);
			}
			@Override
			public void keyPressed(KeyEvent e) {
				int code = e.getKeyCode();
				// fire key
				if(code == fireKey)
					userInput.setFire(true);
				// direction key handling
				if (isDirKey(code)) {
					if (userInput.getDir() != CONSTS.NODIR) {
						// add the key to the list if not exist
						if (userInput.getDir() != keyToDir.get(code) && !keys.contains(code))
							keys.add(code);
						return;
					}
					userInput.setDir(keyToDir.get(code).intValue());
				}
			}
			
			@Override
			public void keyReleased(KeyEvent e) {
				int code = e.getKeyCode();
				if(code == fireKey)
					userInput.setFire(false);
				// dir key released
				if (isDirKey(code)) {
					if (keyToDir.get(code) == userInput.getDir()) {
						if (!nextKey())
							userInput.setDir(CONSTS.NODIR);
					} else {
						keys.remove(Integer.valueOf(code));
					}
				}
			}

			private boolean isDirKey(int code) {
				if(code == upKey) return true;
				if(code == rightKey) return true;
				if(code == downKey) return true;
				if(code == leftKey) return true;
				return false;
			}
			
			private boolean nextKey() {
				if(keys.size() == 0)
					return false;
				int code = keys.get(0);
				keys.remove(0);
				userInput.setDir(keyToDir.get(code));
				return true;
			}
		};
		
		focusAdapter = new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				keys.clear();
				userInput.setDir(CONSTS.NODIR);
				userInput.setFire(false);
			}
		};
	}
	
	public KeyAdapter keyAdapter;
	public FocusAdapter focusAdapter;
	
	public void setControlStatus(ControlStatus cs) {
		userInput = cs;
	}
}